Skip to content

Conversation

@mattleibow
Copy link
Contributor

@mattleibow mattleibow commented Jun 21, 2020

Description of Change

This PR fine tunes the disposal steps of a co-owned object pair. There are a few scenarios:

  1. A managed creates and owns an underlying native instance. (SKBitmap)
    When the managed object is disposed, destroy the native object.
  2. A native object creates a child native object that is managed on the native side. (SKSurface controls SKCanvas)
    When then the managed object destroys the native surface, the native canvas is also destroyed. There may be a case where a brand new native canvas is constructed in the same place - before the managed canvas is disposed. We have to make sure that e dispose the managed object before we destroy the native object.
  3. A native object "creates" a managed object that is managed from the native side. (SKSvgCanvas controls SKManagedStream)
    The managed object creates the native object, but the native object owns the managed object. This means that even when the managed object is disposed, the action is "ignored" and proxied to the native destructor - which will then call back into managed code to dispose the managed object. This is because the native canvas may flush or write closing data into the managed stream.

Scenarios 2 and 3 cause an issue: In one case, the managed SKCanvas needs to be destroyed before destroying the native SkSurface. On the other hand, the native SKSvgCanvas needs to be destroyed before destroying the managed SKManagedStream. So which goes first?

The answer is in the ownership of the handle: In scenario 1, the surface owns its handle and the canvas - which does not own its handle. In scenario 2, the canvas owns its handle and the stream - which does own its handle.

This shows that we need to first dispose all the "reference-only" objects - or the ones that do not own their handle. Then dispose the native object. Finally, clean up any managed objects.

Bugs Fixed

API Changes

None.

Behavioral Changes

See description...

PR Checklist

  • Has tests (if omitted, state reason in description)
  • Rebased on top of master at time of PR
  • Changes adhere to coding standard
  • Updated documentation

This is to ensure that when the next call to create a managed object that has the same native handle (such as in a multithreaded environment) the managed object is always brand new. And, no matter what happens to the native object - such as a disposal/recreate or a swap - the manage object is unaffected.
Fixes #1343
@mattleibow mattleibow changed the title Dispose the native object first Correctly dispose (again) the managed/native object relationship Jun 21, 2020
@mattleibow mattleibow merged commit 57c3b57 into master Jun 21, 2020
@mattleibow mattleibow deleted the dev/fix-1343 branch June 21, 2020 19:21
@mattleibow mattleibow added this to the v2.80.0 milestone Jul 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] SKCanvas owned by SKSurface gets disposed

2 participants